import axios from 'axios';
import {
    ElLoading,
    ElMessage
} from 'element-plus';
import GlobalParameters from './globalConfig';
import store from '@/store';
import {
    REQ_ENQUEUE_ACTION,
    GET_USER
} from '@/utils/Const';

axios.defaults.withCredentials = true; // 需要跨域携带认证
axios.defaults.headers.common['Content-Type'] =
    'application/json;charset=UTF-8';
class Httprequest {
    constructor() {
        this.timeout = 50000; // 请求的超时时间50秒
        this.queue = {}; // 请求队列,防止重复点击
        this.loadingCount = 0;
        this.loadingInstance;
    }

    _closeLoading(isLoading) {
        if (isLoading) {
            this.loadingCount--;
            if (this.loadingCount <= 0) {
                this.loadingInstance.close();
                this.loadingCount = 0;
            }
        }
    }

    setinterceptors(instance, isLoading, isCancel, unique) {
        instance.interceptors.request.use((config) => {
            const user = store.getters[`user/${GET_USER}`];
            if (user && user.accessToken) {
                config.headers['Authorization'] = 'Bearer ' + user.accessToken;
            }
            if (config.method.toUpperCase() === 'GET') {
                config.params = {
                    ...GlobalParameters,
                    ...config.params
                };
            } else {
                // 文件流全局参数处理
                if (config.headers['Content-Type'] === 'multipart/form-data') {
                    Object.keys(GlobalParameters).forEach((key) => {
                        config.data.append(key, GlobalParameters[key]);
                    });
                } else {
                    config.data = {
                        ...GlobalParameters,
                        ...config.data
                    };
                }
            }
            if (this.queue[unique]) {
                throw 'EXCEPTION:REPEATCLICK';
            } else {
                this.queue[unique] = unique;
            }

            if (isLoading) {
                this.loadingCount++;
                this.loadingInstance = ElLoading.service({
                    lock: true,
                    text: 'Loading',
                    spinner: 'el-icon-loading',
                    background: 'rgba(0, 0, 0, 0.6)'
                });
            }
            if (isCancel) {
                config.cancelToken = new axios.CancelToken((cancel) => {
                    store.dispatch(`reqCancel/${REQ_ENQUEUE_ACTION}`, cancel);
                });
            }

            return config;
        });

        instance.interceptors.response.use(
            (res) => {
                delete this.queue[unique];
                this._closeLoading(isLoading);
                // 处理导出数据
                if (res.config.responseType === 'blob') {
                    return Promise.resolve(res);
                }
                if (!res.data.success) {
                    ElMessage({
                        showClose: true,
                        message: res.data.message,
                        type: 'error'
                    });
                    return Promise.reject(res.data);
                }
                return Promise.resolve(res.data.data);
            },
            (error) => {
                this._closeLoading(isLoading);
                if (error === 'EXCEPTION:REPEATCLICK') {
                    ElMessage({
                        showClose: true,
                        message: '请不要重复点击!!!',
                        type: 'warning'
                    });
                } else if (error.__proto__.constructor.name === 'Cancel') {
                    delete this.queue[unique];
                    console.log('请求取消');
                } else {
                    delete this.queue[unique];
                    ElMessage({
                        showClose: true,
                        message: '服务器异常!!!',
                        type: 'error'
                    });
                }

                return Promise.reject(error.message);
            }
        );
    }

    request(options, {
        isLoading = true,
        isCancel = true
    } = {}) {
        let instance = axios.create();
        options.method || (options.method = 'post');
        let config = {
            baseURL: '/api',
            timeout: this.timeout,
            ...options
        };
        // 确定唯一性(路由+接口地址+请求方式)
        const unique =
            `${location.href}${config.method}${config.url}`.toLocaleUpperCase();
        this.setinterceptors(instance, isLoading, isCancel, unique);
        return instance(config);
    }
}

const http = new Httprequest();

export default http.request.bind(http);